/**
 * @file
 * @brief 板级描述层：初始化
 * @author
 * + 隐星魂 (Roy Sun) <xwos@xwos.tech>
 * @copyright
 * + Copyright © 2015 xwos.tech, All Rights Reserved.
 * > Licensed under the Apache License, Version 2.0 (the "License");
 * > you may not use this file except in compliance with the License.
 * > You may obtain a copy of the License at
 * >
 * >         http://www.apache.org/licenses/LICENSE-2.0
 * >
 * > Unless required by applicable law or agreed to in writing, software
 * > distributed under the License is distributed on an "AS IS" BASIS,
 * > WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * > See the License for the specific language governing permissions and
 * > limitations under the License.
 */

#include "Board/std.h"
#include <xwcd/soc/arm/v7m/arch_init.h>
#include <xwcd/soc/arm/v7m/m4/stm32/soc_init.h>
#include <xwos/mm/mempool/allocator.h>
#include <xwos/up/thd.h>
#include <xwos/up/swt.h>
#include <xwos/up/sync/rtsem.h>
#include <xwos/up/sync/cond.h>
#include <xwos/up/sync/evt.h>
#include <xwos/up/lock/mtx.h>
#include "XWAC/xwos/pm.h"
#include "XWAC/xwds/device.h"
#include "STM32Cube/mif.h"

extern xwsz_t ccmram_mr_origin[];
extern xwsz_t ccmram_mr_size[];
extern xwsz_t ccmram_mr_pos[];
#define CCMRAM_PAGE_ORDER 4 /* 64K / 4K == 16 == exp2(4) */
/**
 * @brief CCMRAM内存池
 * @note
 * + 头文件
 *   - Board/ccmram.h
 * + API
 *   - 申请：xwmm_mempool_malloc(ccmram_mempool, ...)
 *   - 释放：xwmm_mempool_free(ccmram_mempool, ...)
 *   - 重新申请：xwmm_mempool_realloc(ccmram_mempool, ...)
 */
__xwbsp_data XWMM_MEMPOOL_DEF(ccmram_mempool, CCMRAM_PAGE_ORDER);

extern xwsz_t isram_mr_origin[];
extern xwsz_t isram_mr_size[];
extern xwsz_t isram_mr_pos[];
#define ISRAM_PAGE_ORDER 5 /* 128K / 4K == 32 == exp2(5) */
/**
 * @brief ISRAM内存池
 * @note
 * + 头文件
 *   - Board/isram.h
 * + API
 *   - 申请：xwmm_mempool_malloc(isram_mempool, ...)
 *   - 释放：xwmm_mempool_free(isram_mempool, ...)
 *   - 重新申请：xwmm_mempool_realloc(isram_mempool, ...)
 */
__xwbsp_data XWMM_MEMPOOL_DEF(isram_mempool, ISRAM_PAGE_ORDER);

#if defined(BRDCFG_MM_EXTSRAM) && (1 == BRDCFG_MM_EXTSRAM)
extern xwu8_t sram_mr_origin[];
extern xwu8_t sram_mr_size[];

/**
 * @brief SRAM内存池
 * @note
 * + 头文件
 *   + `Board/sram.h`
 * + API
 *   + 申请： `xwmm_mempool_malloc(sram_mempool, ...)`
 *   + 释放： `xwmm_mempool_free(sram_mempool, ...)`
 *   + 重新申请： `xwmm_mempool_realloc(sram_mempool, ...)`
 */
struct xwmm_mempool * sram_mempool = (void *)sram_mr_origin;
#endif

/**
 * @brief 初始化内存管理
 */
static __xwbsp_init_code
void board_mm_init(void)
{
        xwer_t rc;
        xwsz_t used;

        used = (xwsz_t)ccmram_mr_pos - (xwsz_t)ccmram_mr_origin;
        rc = xwmm_mempool_init((struct xwmm_mempool *)ccmram_mempool, "CCMRAM",
                               (xwptr_t)ccmram_mr_origin,
                               (xwsz_t)ccmram_mr_size,
                               CCMRAM_PAGE_ORDER,
                               used, NULL);
        BOARD_BUG_ON(rc < 0);

        used = (xwsz_t)isram_mr_pos - (xwsz_t)isram_mr_origin;
        rc = xwmm_mempool_init((struct xwmm_mempool *)isram_mempool, "ISRAM",
                               (xwptr_t)isram_mr_origin,
                               (xwsz_t)isram_mr_size,
                               (xwsz_t)ISRAM_PAGE_ORDER,
                               used, NULL);
        BOARD_BUG_ON(rc < 0);

#if defined(BRDCFG_MM_EXTSRAM) && (1 == BRDCFG_MM_EXTSRAM)
        xwssq_t odr;

        odr = xwbop_fls(xwsz_t, (xwsz_t)sram_mr_size / XWMM_MEMPOOL_PAGE_SIZE);
        rc = xwmm_mempool_init(sram_mempool, "SRAM",
                               (xwptr_t)sram_mr_origin,
                               (xwsz_t)sram_mr_size,
                               (xwsz_t)odr,
                               (xwsz_t)0, NULL);
        BOARD_BUG_ON(rc < 0);
#endif

        rc = xwup_thd_cache_init((struct xwmm_mempool *)isram_mempool,
                                 (xwsz_t)BRDCFG_XWOS_THD_CACHE_ODR);
        BOARD_BUG_ON(rc < 0);

        rc = xwup_swt_cache_init((struct xwmm_mempool *)isram_mempool,
                                 (xwsz_t)BRDCFG_XWOS_SWT_CACHE_ODR);
        BOARD_BUG_ON(rc < 0);

        rc = xwup_rtsem_cache_init((struct xwmm_mempool *)isram_mempool,
                                   (xwsz_t)BRDCFG_XWOS_SEM_CACHE_ODR);
        BOARD_BUG_ON(rc < 0);

        rc = xwup_cond_cache_init((struct xwmm_mempool *)isram_mempool,
                                  (xwsz_t)BRDCFG_XWOS_COND_CACHE_ODR);
        BOARD_BUG_ON(rc < 0);

        rc = xwup_evt_cache_init((struct xwmm_mempool *)isram_mempool,
                                 (xwsz_t)BRDCFG_XWOS_EVT_CACHE_ODR);
        BOARD_BUG_ON(rc < 0);

        rc = xwup_mtx_cache_init((struct xwmm_mempool *)isram_mempool,
                                 (xwsz_t)BRDCFG_XWOS_MTX_CACHE_ODR);
        BOARD_BUG_ON(rc < 0);
}

/**
 * @brief XWOS预初始化
 */
__xwbsp_init_code
void xwos_preinit(void)
{
        arch_init();
        soc_init();
        stm32cube_preinit();
        soc_relocate_data();
        soc_relocate_ivt();
        stm32cube_init();
}

/**
 * @brief XWOS后初始化
 */
__xwbsp_init_code
void xwos_postinit(void)
{
        stm32xwds_init();
        stm32xwds_soc_init();
        xwosac_pmcb_init();
        board_mm_init();
}
